package com.zx._01_基础._015_编码技巧;

import com.google.common.base.Joiner;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;
import com.google.common.collect.Table;
import com.zx.common.entity.User;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.junit.Test;

@Slf4j
public class 字符串与集合 {

    private static final List<String> list = Lists.newArrayList("1", "2", "3");

    private static final List<String> list2 = Lists.newArrayList("2", "3", "6", "1", "2");

    /**
     * List集合拼接成以逗号分隔的字符串
     */
    @Test
    public void test01() {
        // 方式1:使用stream拼接
        String s1 = list.stream().collect(Collectors.joining(","));
        log.info("s1={}", s1);
        // 方式2：使用string自带方法
        String s2 = String.join(",", list);
        log.info("s2={}", s2);
    }

    /**
     * 比较两个字符串是否相等，忽略大小写
     */
    @Test
    public void test02() {
        System.out.println("a".equalsIgnoreCase("A"));
    }

    /**
     * 两个List集合取交集
     */
    @Test
    public void test03() {
        /*
        list = [1, 2, 3]
        list2 = [2, 3, 6, 1, 2]
        对list2进行取交集的运算：获得[2, 3, 1, 2]
         */
        boolean b = list2.retainAll(list);

        log.info("list2={}, b={}", list2, b);
    }

    /**
     * 使用commons-lang3
     * 字符串判空
     */
    @Test
    public void test04() {
        //传参CharSequence类型是String、StringBuilder、StringBuffer的父类，都可以直接下面方法判空
        String str = null;

        boolean empty = StringUtils.isEmpty(str);
        log.info("empty={}", empty);

        boolean notEmpty = StringUtils.isNotEmpty(str);
        log.info("notEmpty={}", notEmpty);

        // 判空的时候，会去除字符串中的空白字符，比如空格、换行、制表符
        String str2 = "\t";
        boolean blank = StringUtils.isBlank(str2);
        log.info("blank={}", blank);
    }

    /**
     * 使用commons-lang3
     * 首字母转成大写/小写
     */
    @Test
    public void test05() {
        String str = "abc";
        String capitalize = StringUtils.capitalize(str);
        log.info("capitalize={}", capitalize);

        String str2 = "ABC";
        String uncapitalize = StringUtils.uncapitalize(str2);
        log.info("uncapitalize={}", uncapitalize);


    }

    /**
     * 使用commons-lang3
     * 重复拼接字符串
     */
    @Test
    public void test06() {
        // 重复三遍
        String repeat = StringUtils.repeat("abc", 3);
        log.info("repeat={}", repeat);
    }

    /**
     * 使用commons-lang3
     * 集合操作
     */
    @Test
    public void test07() {
        // 两个集合取交集
        Collection<String> c1 = CollectionUtils.retainAll(list, list2);
        // 两个集合取并集
        Collection<String> c2 = CollectionUtils.union(list, list2);
        // 两个集合取差集
        Collection<String> c3 = CollectionUtils.subtract(list, list2);
        log.info("c1={}", c1);
        log.info("c2={}", c2);
        log.info("c3={}", c3);
    }

    /**
     * Google Guava 工具类库
     * 创建集合
     */
    @Test
    public void test08() {

        List<String> aaa = Lists.newArrayList();
        List<Integer> bbb = Lists.newArrayList(1, 2, 3);

        // 反转list

        List<Integer> reverse = Lists.reverse(bbb);
        System.out.println(reverse); // 输出 [3, 2, 1]

        // list集合元素太多，可以分成若干个集合，每个集合10个元素
        List<List<Integer>> partition = Lists.partition(bbb, 10);

        Map<String, String> map = Maps.newHashMap();
        Set<String> set = Sets.newHashSet();
    }

    /**
     * 【重要】Multimap 一个key可以映射多个value的HashMap
     */
    @Test
    public void test09() {
        Multimap<String, Integer> map = ArrayListMultimap.create();
        map.put("key", 1);
        map.put("key", 2);

        Collection<Integer> values = map.get("key");
        System.out.println(map); // {key=[1, 2]}

        // 还能返回你以前使用的臃肿的Map
        Map<String, Collection<Integer>> collectionMap = map.asMap();
        log.info("collectionMap={}", collectionMap);//collectionMap={key=[1, 2]}
    }

    /**
     * BiMap 一种连value也不能重复的HashMap
     */
    @Test
    public void test10() {
        BiMap<String, String> biMap = HashBiMap.create();
        // 如果value重复，put方法会抛异常，除非用forcePut方法
        biMap.put("key", "value");
        System.out.println(biMap); // 输出 {"key":"value"}

        // 既然value不能重复，何不实现个翻转key/value的方法，已经有了
        BiMap<String, String> inverse = biMap.inverse();
        System.out.println(inverse); // 输出 {"value":"key"}
    }

    /**
     * Table 一种有两个key的HashMap
     */
    @Test
    public void test11() {
        // 一批用户，同时按年龄和性别分组
        Table<Integer, String, String> table = HashBasedTable.create();
        table.put(18, "男", "yideng");
        table.put(18, "女", "Lily");
        System.out.println(table.get(18, "男")); // 输出 yideng

        // 这其实是一个二维的Map，可以查看行数据
        Map<String, String> row = table.row(18);
        System.out.println(row); // 输出 {"男":"yideng","女":"Lily"}

        // 查看列数据
        Map<Integer, String> column = table.column("男");
        System.out.println(column); // 输出 {18:"yideng"}

        log.info("blank={}", 1);
    }

    /**
     * Multiset 一种用来计数的Set
     */
    @Test
    public void test12() {
        Multiset<String> multiset = HashMultiset.create();
        multiset.add("apple");
        multiset.add("apple");
        multiset.add("orange");
        System.out.println(multiset.count("apple")); // 输出 2

        // 查看去重后的元素
        Set<String> set = multiset.elementSet();
        System.out.println(set); // 输出 ["orange","apple"]

        // 还能查看没有去重的元素
        Iterator<String> iterator = multiset.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }

        // 还能手动设置某个元素出现的次数
        multiset.setCount("apple", 5);
        System.out.println(multiset);// [orange, apple x 5]
    }

    /**
     * @Title: 字符串累加(集合)(Guava)
     * @date: 2019年2月15日下午10:16:13
     * @author: zhangxue
     */
    @Test
    public void test13() {
        // 字符串只要不在for循环里累加，可以直接用+号，
        // 因为编译成字节码后会变成StringBuilder，
        // 如果在for循环里面用+号会生成多个StringBuilder，
        // 所以在for循环里累加最好在循环外创建StringBuilder。

        // 拼接集合
        final List<User> list = Arrays.asList(
                new User(1L, "A", 16),
                new User(2L, "B", 16),
                new User(3L, "C", 16));
        System.out.println(Joiner.on(" # ").join(list));

        // 拼接map，元素之间使用 | 隔开， key value之间使用 = 隔开
        final String sblog = Joiner.on("|")
                .withKeyValueSeparator("=")
                .join(ImmutableMap.of("aa", "bb", "cc", "dd"));
        System.out.println(sblog);

    }

    /**
     * @Title: list to map(JDK8)
     * @date: 2019年2月15日下午10:33:34
     * @author: zhangxue
     */
    @Test
    public void test14() {
        final List<User> list = Arrays.asList(
                new User(1L, "A", 16),
                new User(2L, "B", 16),
                new User(3L, "C", 16));
        final Map<String, User> map = list.stream().collect(Collectors.toMap(ele -> ele.getName(), ele -> ele));
        System.out.println(map);
    }

    /**
     *
     */
    @Test
    public void test15() {
        // jdk 11 之前可以这样写
        Set<String> set = new HashSet<String>() {{
            this.add("wmyskxz");
            this.add("is");
            this.add("awesome");
            this.add("!");
        }};
        System.out.println(set);
        log.info("blank={}", 1);
    }

}
